/**
 * 
 */
package services.communication.mail;

import java.rmi.RemoteException;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import org.example.www.communication.MailService.CommunicationMailService_PortType;
import org.example.www.communication.MailService.EMail;
import org.example.www.communication.MailService.emailServer.EMailSenderComparator;

import services.communication.mail._dynamic.CommunicationMailServiceIF;

/**
 * La clase es un cliente de mail, que utiliza un
 * {@link CommunicationMailService_PortType} para acceder al web-sevice de
 * e-mail.<BR/>
 * 
 * @author lito
 */
public class SimpleMailClient implements SimpleMailClientIF {
	
	/**
	 * El identificador del cliente. E-mail del usuario.
	 */
	private String								clientID;
	
	/**
	 * Cantidad de e-amils enviados por la instancia.
	 */
	private int									sendMailcount;
	
	/**
	 * Lista de los EMails recividos en la ultima llamada al metodo de
	 * recepcion.
	 */
	private List<EMail>							recivedMails;
	
	/**
	 * Proxy para acceder al web-service de e-mail.
	 */
	private CommunicationMailService_PortType	mailServiceProxy;
	
	/**
	 * Proxy para acceder al web-service de e-mail via spring.
	 */
	private CommunicationMailServiceIF			springMailServiceProxy;
	
	/**
	 * Constructor por defecto. Inicializa el cliente en null, la cuenta de
	 * e-mails enviads en cero, la lista de mensajes recividos en nulo y el
	 * proxy en nulo.
	 */
	public SimpleMailClient() {
		this.clientID = null;
		this.sendMailcount = 0;
		this.recivedMails = new Vector<EMail>();
		this.mailServiceProxy = null;
		this.springMailServiceProxy = null;
	}
	
	/**
	 * @return Proxy para acceder al web-service de e-mail via spring.
	 */
	public synchronized final CommunicationMailServiceIF getSpringMailServiceProxy() {
		return springMailServiceProxy;
	}
	
	/**
	 * @param springMailServiceProxy
	 *        Proxy para acceder al web-service de e-mail via spring.
	 */
	public synchronized final void setSpringMailServiceProxy(
			CommunicationMailServiceIF springMailServiceProxy) {
		this.springMailServiceProxy = springMailServiceProxy;
	}
	
	/**
	 * @return Proxy para acceder al web-service de e-mail.
	 */
	public synchronized final CommunicationMailService_PortType getMailServiceProxy() {
		return mailServiceProxy;
	}
	
	/**
	 * @param setMailServiceProxy
	 *        Proxy para acceder al web-service de e-mail.
	 */
	public synchronized final void setMailServiceProxy(
			CommunicationMailService_PortType mailServiceProxy) {
		this.mailServiceProxy = mailServiceProxy;
	}
	
	/**
	 * @return El identificador del cliente. E-mail del usuario.
	 */
	public synchronized final String getClientID() {
		return clientID;
	}
	
	/**
	 * Si el parametro es distinto del id de cliente actual, vuelve la cuenta de
	 * mails enviados a cero. limpia la lista de mails recividos; si no, no hace
	 * nada.
	 * 
	 * @param clientID
	 *        El identificador del cliente. E-mail del usuario.
	 */
	public synchronized final void setClientID(String clientID) {
		if (!clientID.equals(this.clientID)) {
			this.sendMailcount = 0;
			this.recivedMails.clear();
			this.clientID = clientID;
		}
	}
	
	/**
	 * @return Cantidad de e-amils enviados por la instancia.
	 */
	public synchronized final int getSendMailcount() {
		return sendMailcount;
	}
	
	/**
	 * @return Lista de los EMails recividos en la ultima llamada al metodo de
	 *         recepcion.
	 */
	public synchronized final List<EMail> getRecivedMails() {
		return recivedMails;
	}
	
	/**
	 * Invoca el metodo
	 * {@link CommunicationMailService_PortType#reciveEMails(String)} de la
	 * instancia interna {@link SimpleMailClient#mailServiceProxy} en caso de
	 * que este seteada, si el proxy sping esta seteado, se invoca el metodos de
	 * este ultimo. para obtener los e-mails del cliente que tenga seteada esta
	 * instancia.<BR/>
	 * Luego construye una lista a partir del arreglo de EMails seteando
	 * {@link #recivedMails}.<BR/>
	 * 
	 * @throws RuntimeException
	 *         En caso de que ocurra una {@link RemoteException}.
	 */
	public void reciveEMails() {
		try {
			if (this.springMailServiceProxy != null) {
				java.util.ArrayList<EMail> emails = this.springMailServiceProxy
						.reciveEMails(this.clientID);
				this.recivedMails.clear();
				if (emails != null) {
					for (EMail email : emails)
						if (email != null)
							this.recivedMails.add(email);
				}
			} else if (this.mailServiceProxy != null) {
				EMail[] emails = this.mailServiceProxy
						.reciveEMails(this.clientID);
				this.recivedMails.clear();
				if (emails != null) {
					for (EMail email : emails)
						if (email != null)
							this.recivedMails.add(email);
				}
			}
		} catch (RemoteException e) {
			throw new RuntimeException(ERROR_MSG_RECIVE_EMAILS, e);
		}
	}
	
	/**
	 * Envia el e-mail pasado como parametro mediante el proxy interno.
	 * Incrementa en uno la cuenta de e-mails de la instancia.
	 * 
	 * @param email
	 *        El e-mail a enviar.
	 * @throws Exception
	 *         En caso de que ocurra una {@link RemoteException}.<BR/>
	 *         O en caso de que el metodo
	 *         {@link CommunicationMailService_PortType#sendEMail(EMail)}
	 *         retorne false.
	 */
	public void sendEMail(EMail email) throws Exception {
		try {
			if (this.springMailServiceProxy != null) {
				if (!this.springMailServiceProxy.sendEMail(email)) {
					throw new Exception(ERROR_MSG_SEND_EMAIL);
				}
				++this.sendMailcount;
			} else if (this.mailServiceProxy != null) {
				if (!this.mailServiceProxy.sendEMail(email)) {
					throw new Exception(ERROR_MSG_SEND_EMAIL);
				}
				++this.sendMailcount;
			}
		} catch (RemoteException e) {
			throw new Exception(ERROR_MSG_SEND_EMAIL, e);
		}
	}
	
	/**
	 * Retorna una lista con los e-mails que se hayan recivido en el ultimo
	 * llamado del metodo {@link #reciveEMails()}.<BR/>
	 * Este metodo no afecta la lista que se devuelve con el metodo
	 * {@link #getRecivedMails()}.
	 * 
	 * @return Una lista con los e-mails que se hayan recivido en el ultimo
	 *         llamado del metodo {@link #reciveEMails()}.
	 */
	public List<EMail> getRecivedEMailsOrderBySender() {
		List<EMail> sortedEMails = new Vector<EMail>(this.recivedMails);
		Collections.sort(sortedEMails, EMailSenderComparator.getInstance());
		return sortedEMails;
	}
	
}
